{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101 -> 5\n",
      "------------------------\n",
      "+0101 -> 5\n",
      "------------------------\n",
      "-0101 -> -5\n",
      "------------------------\n",
      " \n",
      "0b_1_110   \n",
      "\n",
      " -> 14\n",
      "------------------------\n",
      "  +0b1110 \n",
      "  -> 14\n",
      "------------------------\n",
      "-0b1110 -> -14\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def bin2dec(bin_str: str) -> int:\n",
    "    '''\n",
    "    函数功能：不带符号位的2进制字符串 -> 10进制整数\\n\n",
    "    输入：2进制字符串，可带正负号，0b，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输出：10进制整数，只保留负号，正号不保留\n",
    "    '''\n",
    "    return int(bin_str.strip(), base = 2)\n",
    "\n",
    "ls = ['101', '+0101' , '-0101', ' \\n0b_1_110   \\n\\n', '  +0b1110 \\n ', '-0b1110']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + str(bin2dec(a)))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "00000101 -> 0x5\n",
      "00000101 -> 0x5\n",
      "------------------------\n",
      "+0101 -> 0x5\n",
      "+0101 -> 0x5\n",
      "------------------------\n",
      "-0101 -> -0x5\n",
      "-0101 -> -0x5\n",
      "------------------------\n",
      "0b1110 -> 0xe\n",
      "0b1110 -> 0xe\n",
      "------------------------\n",
      "+0b10110 -> 0x16\n",
      "位宽参数1 < 2进制+0b10110输出16进制0x16实际位宽2，请修正位宽参数\n",
      "+0b10110 -> 0x16\n",
      "------------------------\n",
      "-0b1110 -> -0xe\n",
      "-0b1110 -> -0xe\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def bin2hex(bin_str: str, hex_width :int = -1) -> str:\n",
    "    '''\n",
    "    函数功能：不带符号位的2进制字符串 -> 不带符号位的16进制字符串\\n\n",
    "    输入参数1：2进制字符串，可带正负号，0b，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输入参数2：可选，16进制字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干0\\n\n",
    "    输出：16进制字符串，只保留负号，正号不保留\n",
    "    '''\n",
    "    new_bin_str = bin_str.strip()\n",
    "    if (new_bin_str[0] == '+' or new_bin_str[0] == '-'): # 去除正负符号\n",
    "        new_bin_str = new_bin_str[1:]\n",
    "    if (new_bin_str[:2] == '0b'):\n",
    "        new_bin_str = new_bin_str[2:]\n",
    "    hex_str = hex(int(new_bin_str, base = 2))[2:]\n",
    "    if (hex_width == -1):\n",
    "        pass\n",
    "    elif (hex_width < len(hex_str)): # 位宽小于实际16进制数位宽时\n",
    "        print('位宽参数' + str(hex_width) + ' < 2进制' + bin_str + '输出16进制' + '0x' + hex_str\n",
    "            + '实际位宽' + str(len(hex_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        hex_str = '0' * (hex_width - len(hex_str)) + hex_str # 扩展位补0\n",
    "    if (bin_str[0] == '-'):\n",
    "        return '-' + '0x' + hex_str\n",
    "    else:\n",
    "        return '0x' + hex_str\n",
    "\n",
    "ls = ['00000101', '+0101' , '-0101', '0b1110', '+0b10110', '-0b1110']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + bin2hex(a))\n",
    "    print(a + ' -> ' + bin2hex(a, 1))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101 -> 0b1100101\n",
      "101 -> 0b001100101\n",
      "------------------------\n",
      "+0101 -> 0b1100101\n",
      "+0101 -> 0b001100101\n",
      "------------------------\n",
      "-0101 -> -0b1100101\n",
      "-0101 -> -0b001100101\n",
      "------------------------\n",
      "0110 -> 0b1101110\n",
      "0110 -> 0b001101110\n",
      "------------------------\n",
      "+01010 -> 0b1111110010\n",
      "位宽参数9 < 10进制+01010输出2进制0b1111110010最小需要位宽10，请修正位宽参数\n",
      "+01010 -> 0b1111110010\n",
      "------------------------\n",
      "-100000 -> -0b11000011010100000\n",
      "位宽参数9 < 10进制-100000输出2进制-0b11000011010100000最小需要位宽17，请修正位宽参数\n",
      "-100000 -> -0b11000011010100000\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def dec2bin(dec_num: int, bin_width :int = -1) -> str:\n",
    "    '''\n",
    "    函数功能：10进制整数/字符串 -> 不带符号位的2进制字符串\\n\n",
    "    输入参数1：10进制整数/字符串，可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输入参数2：可选，2进制字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干0\\n\n",
    "    输出：16进制字符串，只保留负号，正号不保留\n",
    "    '''\n",
    "    input_dec_num = dec_num\n",
    "    if (type(dec_num) == str):\n",
    "        dec_num = int(dec_num.strip())\n",
    "    old_bin_str = bin(dec_num)\n",
    "    if (old_bin_str[0] == '-'):\n",
    "        bin_str = old_bin_str[3:]\n",
    "    else:\n",
    "        bin_str = old_bin_str[2:]\n",
    "    if (bin_width == -1):\n",
    "        pass\n",
    "    elif (bin_width < len(bin_str)):\n",
    "        print('位宽参数' + str(bin_width) + ' < 10进制' + str(input_dec_num) + '输出2进制' + old_bin_str\n",
    "            + '最小需要位宽' + str(len(bin_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        bin_str = '0' * (bin_width - len(bin_str)) + bin_str\n",
    "    if (old_bin_str[0] == '-'):\n",
    "        return '-0b' + bin_str\n",
    "    else:\n",
    "        return '0b' + bin_str\n",
    "\n",
    "ls = ['101', '+0101' , '-0101', '0110', '+01010', '-100000']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + dec2bin(a))\n",
    "    print(a + ' -> ' + dec2bin(a, 9))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101 -> 0x65\n",
      "101 -> 0x65\n",
      "------------------------\n",
      "+0101 -> 0x65\n",
      "+0101 -> 0x65\n",
      "------------------------\n",
      "-0101 -> -0x65\n",
      "-0101 -> -0x65\n",
      "------------------------\n",
      "0110 -> 0x6e\n",
      "0110 -> 0x6e\n",
      "------------------------\n",
      "+255 -> 0xff\n",
      "+255 -> 0xff\n",
      "------------------------\n",
      "-256 -> -0x100\n",
      "位宽参数2 < 10进制-256输出16进制-0x100实际位宽3，请修正位宽参数\n",
      "-256 -> -0x100\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def dec2hex(dec_num: int , hex_width: int = -1) -> str:\n",
    "    '''\n",
    "    函数功能：10进制整数/字符串 -> 不带符号位的16进制字符串\\n\n",
    "    输入参数1：10进制整数/字符串，可带正负号，前后可加任意个 \\n 和 空格，数字间可加下划线\\n\n",
    "    输入参数2：可选，16进制字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干0\\n\n",
    "    输出：16进制字符串，只保留负号，正号不保留\n",
    "    '''\n",
    "    old_hex_str = bin2hex(dec2bin(dec_num))\n",
    "    if (old_hex_str[0] == '-'):\n",
    "        hex_str = old_hex_str[3:]\n",
    "    else:\n",
    "        hex_str = old_hex_str[2:]\n",
    "    if (hex_width == -1):\n",
    "        pass\n",
    "    elif (hex_width < len(hex_str)):\n",
    "        print('位宽参数' + str(hex_width) + ' < 10进制' + str(dec_num) + '输出16进制' + old_hex_str\n",
    "            + '实际位宽' + str(len(hex_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        hex_str = '0' * (hex_width - len(hex_str)) + hex_str\n",
    "    if (old_hex_str[0] == '-'):\n",
    "        return '-0x' + hex_str\n",
    "    else:\n",
    "        return '0x' + hex_str\n",
    "\n",
    "ls = ['101', '+0101' , '-0101', '0110', '+255', '-256']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + dec2hex(a))\n",
    "    print(a + ' -> ' + dec2hex(a, 2))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101 -> 257\n",
      "------------------------\n",
      "+0101 -> 257\n",
      "------------------------\n",
      "-0101 -> -257\n",
      "------------------------\n",
      "0110 -> 272\n",
      "------------------------\n",
      "+255 -> 597\n",
      "------------------------\n",
      "-2256 -> -8790\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def hex2dec(hex_str: str) -> int:\n",
    "    '''\n",
    "    函数功能：不带符号位的16进制字符串 -> 10进制整数\\n\n",
    "    输入：16进制字符串，可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输出：10进制整数，只保留负号，正号不保留\n",
    "    '''\n",
    "    return int(hex_str.strip(), base = 16)\n",
    "\n",
    "ls = ['101', '+0101' , '-0101', '0110', '+255', '-2256']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + str(hex2dec(a)))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101 -> 0b100000001\n",
      "101 -> 0b100000001\n",
      "------------------------\n",
      "+0101 -> 0b100000001\n",
      "+0101 -> 0b100000001\n",
      "------------------------\n",
      "-0101 -> -0b100000001\n",
      "-0101 -> -0b100000001\n",
      "------------------------\n",
      "-0100 -> -0b100000000\n",
      "-0100 -> -0b100000000\n",
      "------------------------\n",
      "+255 -> 0b1001010101\n",
      "位宽参数9 < 16进制+255输出2进制0b1001010101实际位宽10，请修正位宽参数\n",
      "+255 -> 0b1001010101\n",
      "------------------------\n",
      "-256 -> -0b1001010110\n",
      "位宽参数9 < 16进制-256输出2进制-0b1001010110实际位宽10，请修正位宽参数\n",
      "-256 -> -0b1001010110\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def hex2bin(hex_str: str, bin_width = -1) -> str:\n",
    "    '''\n",
    "    函数功能：不带符号位的16进制字符串 -> 不带符号位的2进制字符串\\n\n",
    "    输入：16进制字符串，可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输入参数2：可选，2进制字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干0\\n\n",
    "    输出：2进制字符串，只保留负号，正号不保留\n",
    "    '''\n",
    "    old_bin_str = dec2bin(hex2dec(hex_str))\n",
    "    if (old_bin_str[0] == '-'):\n",
    "        bin_str = old_bin_str[3:]\n",
    "    else:\n",
    "        bin_str = old_bin_str[2:]\n",
    "    if (bin_width == -1):\n",
    "        pass\n",
    "    elif (bin_width < len(bin_str)):\n",
    "        print('位宽参数' + str(bin_width) + ' < 16进制' + hex_str + '输出2进制' + old_bin_str\n",
    "            + '实际位宽' + str(len(bin_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        bin_str = '0' * (bin_width - len(bin_str)) + bin_str\n",
    "    if (old_bin_str[0] == '-'):\n",
    "        return '-0b' + bin_str\n",
    "    else:\n",
    "        return '0b' + bin_str\n",
    "\n",
    "ls = ['101', '+0101' , '-0101', '-0100', '+255', '-256']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + hex2bin(a))\n",
    "    print(a + ' -> ' + hex2bin(a, 9))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101 -> -3\n",
      "------------------------\n",
      "0101 -> 5\n",
      "------------------------\n",
      "0b_0101 -> 5\n",
      "------------------------\n",
      "01_10 -> 6\n",
      "------------------------\n",
      "1_010 -> -22\n",
      "------------------------\n",
      "0b10010 -> -14\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def signed_bin2dec(bin_str: str) -> int:\n",
    "    '''\n",
    "    函数功能：2进制补码字符串 -> 10进制整数\\n\n",
    "    输入：2进制补码字符串，不可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输出：10进制整数，只保留负号，正号不保留\n",
    "    '''\n",
    "    bin_str = bin_str.strip()\n",
    "    if (bin_str[:2] == '0b'):\n",
    "        if (bin_str[2] == '_'):\n",
    "            bin_str = bin_str[3:]\n",
    "        else:\n",
    "            bin_str = bin_str[2:]\n",
    "    if (bin_str[0] == '0'):\n",
    "        return int(bin_str, base = 2)\n",
    "    elif (bin_str[0] == '1'):\n",
    "        return int(bin_str, base = 2) - 2**len(bin_str)\n",
    "    elif (bin_str[0] == '_'):\n",
    "        int ('输入 ' + bin_str + ' 不合法，首字符不能是下划线 且 不允许出现连续两个下划线')\n",
    "    else:\n",
    "        int('输入 ' + bin_str + ' 不合法，必须为2进制补码，不允许带正负号')\n",
    "\n",
    "ls = ['101', '0101' , '0b_0101', '01_10', '1_010', '0b10010']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + str(signed_bin2dec(a)))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0b000000101 -> 0x5\n",
      "0b000000101 -> 0x5\n",
      "------------------------\n",
      "001 -> 0x1\n",
      "001 -> 0x1\n",
      "------------------------\n",
      "0101 -> 0x5\n",
      "0101 -> 0x5\n",
      "------------------------\n",
      "0110 -> 0x6\n",
      "0110 -> 0x6\n",
      "------------------------\n",
      "1010 -> 0xa\n",
      "1010 -> 0xa\n",
      "------------------------\n",
      "0b1011111 -> 0xdf\n",
      "位宽参数1 < 2进制补码0b1011111输出16进制补码0xdf实际位宽2，请修正位宽参数\n",
      "0b1011111 -> 0xdf\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def fourBin2OneHex(four_bin: str) -> str:\n",
    "    '''\n",
    "    函数功能：4位2进制字符串 -> 1位16进制字符串\\n\n",
    "    输入：4位2进制字符串，输入范围0000~1111\\n\n",
    "    输出：1位16进制字符串\n",
    "    '''\n",
    "    if (four_bin == '0000'):\n",
    "        return '0'\n",
    "    elif (four_bin == '0001'):\n",
    "        return '1'\n",
    "    elif (four_bin == '0010'):\n",
    "        return '2'\n",
    "    elif (four_bin == '0011'):\n",
    "        return '3'\n",
    "    elif (four_bin == '0100'):\n",
    "        return '4'\n",
    "    elif (four_bin == '0101'):\n",
    "        return '5'\n",
    "    elif (four_bin == '0110'):\n",
    "        return '6'\n",
    "    elif (four_bin == '0111'):\n",
    "        return '7'\n",
    "    elif (four_bin == '1000'):\n",
    "        return '8'\n",
    "    elif (four_bin == '1001'):\n",
    "        return '9'\n",
    "    elif (four_bin == '1010'):\n",
    "        return 'a'\n",
    "    elif (four_bin == '1011'):\n",
    "        return 'b'\n",
    "    elif (four_bin == '1100'):\n",
    "        return 'c'\n",
    "    elif (four_bin == '1101'):\n",
    "        return 'd'\n",
    "    elif (four_bin == '1110'):\n",
    "        return 'e'\n",
    "    elif (four_bin == '1111'):\n",
    "        return 'f'\n",
    "    else:\n",
    "        int('输入2进制字符' + four_bin + '错误，2进制只能包含0或1')\n",
    "\n",
    "def signed_bin2hex(bin_str: str, hex_width: int = -1) -> str:\n",
    "    '''\n",
    "    函数功能：2进制补码字符串 -> 16进制补码字符串\\n\n",
    "    输入参数1：2进制补码字符串，不可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输入参数2：可选，16进制补码字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干符号位\\n\n",
    "    输出：16进制补码字符串\n",
    "    '''\n",
    "    input_bin_str = bin_str\n",
    "    bin_str = bin_str.strip()\n",
    "    if (bin_str[:2] == '0b'): # 2进制字符串以0b开头\n",
    "        bin_str = bin_str[2:]\n",
    "    elif (bin_str[0] == '0' or bin_str[0] == '1'):\n",
    "        pass\n",
    "    else:\n",
    "        int('输入 ' + bin_str + ' 不合法，输入必须为2进制补码，不允许带正负号 且 首字符不能是下划线')\n",
    "    # 检查输入是否合法，末尾字符不能是下划线 且 不能出现连续的两个下划线\n",
    "    if (bin_str[-1] == '_' or '__' in bin_str):\n",
    "        int('输入 ' + bin_str + ' 不合法，末尾字符不能是下划线 且 不能出现连续的两个下划线')\n",
    "    else:\n",
    "        bin_str = bin_str.replace('_', '') # 输入合法则去除下划线\n",
    "    # 去掉2进制补码字符串前面多余的符号位，保留两位\n",
    "    for i in range(len(bin_str)-1):\n",
    "        if (bin_str[i+1] == bin_str[0]):\n",
    "            if (i + 1 == len(bin_str)-1):\n",
    "                bin_str = bin_str[i:]\n",
    "            else:\n",
    "                continue\n",
    "        else:\n",
    "            bin_str = bin_str[i:]\n",
    "            break\n",
    "    if (len(bin_str) % 4 > 0): # 补符号位到位宽为4的倍数\n",
    "        bin_str = bin_str[0] * (4 - len(bin_str) % 4) + bin_str\n",
    "    hex_str = ''\n",
    "    for i in range(int(len(bin_str)/4)):\n",
    "        hex_str += fourBin2OneHex(bin_str[i*4 : i*4+4])\n",
    "    if (hex_width == -1):\n",
    "        pass\n",
    "    elif (hex_width < len(hex_str)):\n",
    "        print('位宽参数' + str(hex_width) + ' < 2进制补码' + input_bin_str + '输出16进制补码'\n",
    "            + '0x' + hex_str +'实际位宽' + str(len(hex_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        if (hex_str[0] in ['0', '1', '2', '3', '4', '5', '6', '7']):\n",
    "            hex_str = '0' * (hex_width - len(hex_str)) + hex_str\n",
    "        else:\n",
    "            hex_str = 'f' * (hex_width - len(hex_str)) + hex_str\n",
    "    return '0x' + hex_str\n",
    "\n",
    "ls = ['0b000000101', '001' , '0101', '0110', '1010', '0b1011111']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + signed_bin2hex(a))\n",
    "    print(a + ' -> ' + signed_bin2hex(a, 1))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 -> 0b01\n",
      "1 -> 0b00000001\n",
      "------------------------\n",
      "0 -> 0b0\n",
      "0 -> 0b00000000\n",
      "------------------------\n",
      "0101 -> 0b01100101\n",
      "0101 -> 0b01100101\n",
      "------------------------\n",
      "01_1_0 -> 0b01101110\n",
      "01_1_0 -> 0b01101110\n",
      "------------------------\n",
      "\n",
      "   +121_010 -> 0b011101100010110010\n",
      "位宽参数8 < 10进制\n",
      "   +121_010输出2进制补码0b011101100010110010实际位宽18，请修正位宽参数\n",
      "\n",
      "   +121_010 -> 0b011101100010110010\n",
      "------------------------\n",
      "-11111 -> 0b101010010011001\n",
      "位宽参数8 < 10进制-11111输出2进制补码0b101010010011001实际位宽15，请修正位宽参数\n",
      "-11111 -> 0b101010010011001\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def signed_dec2bin(dec_num: int, bin_width: int = -1) -> str:\n",
    "    '''\n",
    "    函数功能：10进制数/字符串 -> 2进制补码字符串\\n\n",
    "    输入参数1：10进制数/字符串，可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输入参数2：可选，2进制补码字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干符号位\\n\n",
    "    输出：2进制补码字符串\n",
    "    '''\n",
    "    dec_num_str = str(dec_num)\n",
    "    if (type(dec_num) == str):\n",
    "        dec_num = int(dec_num.strip())\n",
    "    if (dec_num == 0):\n",
    "        bin_str = '0'\n",
    "    elif (dec_num > 0):\n",
    "        bin_str = '0' + bin(dec_num)[2:] # 补符号位0\n",
    "    else:\n",
    "        for i in range(10000):\n",
    "            if (2**i + dec_num >= 0):\n",
    "                bin_str = bin(2**(i+1) + dec_num)[2:] # 一个负数num的补码等于（2**i + dec_num)\n",
    "                break\n",
    "    if (bin_width == -1):\n",
    "        pass\n",
    "    elif (bin_width < len(bin_str)):\n",
    "        # 实际位宽大于设定位宽则报警告，然后按实际位宽输出\n",
    "        print('位宽参数' + str(bin_width) + ' < 10进制' + dec_num_str + '输出2进制补码'\n",
    "            + '0b' + bin_str + '实际位宽' + str(len(bin_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        bin_str = bin_str[0] * (bin_width - len(bin_str)) + bin_str # 实际位宽小于设定位宽则补符号位\n",
    "    return '0b' + bin_str\n",
    "\n",
    "ls = [1, '0' , '0101', '01_1_0', '\\n   +121_010', '-11111']\n",
    "for a in ls:\n",
    "    print(str(a) + ' -> ' + signed_dec2bin(a))\n",
    "    print(str(a) + ' -> ' + signed_dec2bin(a, 8))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-101 -> 0x9b\n",
      "-101 -> 0xf9b\n",
      "------------------------\n",
      "-010 -> 0xf6\n",
      "-010 -> 0xff6\n",
      "------------------------\n",
      "0101 -> 0x65\n",
      "0101 -> 0x065\n",
      "------------------------\n",
      "0110 -> 0x6e\n",
      "0110 -> 0x06e\n",
      "------------------------\n",
      "1010 -> 0x3f2\n",
      "1010 -> 0x3f2\n",
      "------------------------\n",
      "+11_111 -> 0x2b67\n",
      "位宽参数3 < 10进制+11_111输出16进制补码0x2b67实际位宽4，请修正位宽参数\n",
      "+11_111 -> 0x2b67\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def signed_dec2hex(dec_num: int, hex_width = -1) -> str:\n",
    "    '''\n",
    "    函数功能：10进制数/字符串 -> 16进制补码字符串\\n\n",
    "    输入参数1：10进制数/字符串，可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线_\\n\n",
    "    输入参数2：可选，16进制补码字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干符号位\\n\n",
    "    输出：16进制补码字符串\n",
    "    '''\n",
    "    hex_str = signed_bin2hex(signed_dec2bin(dec_num))[2:]\n",
    "    if (hex_width == -1):\n",
    "        pass\n",
    "    elif (hex_width < len(hex_str)):\n",
    "        print('位宽参数' + str(hex_width) + ' < 10进制' + str(dec_num) + '输出16进制补码' + '0x' +\n",
    "            hex_str + '实际位宽' + str(len(hex_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        if (hex_str[0] in ['0', '1', '2', '3', '4', '5', '6', '7']):\n",
    "            hex_str = '0' * (hex_width - len(hex_str)) + hex_str\n",
    "        else:\n",
    "            hex_str = 'f' * (hex_width - len(hex_str)) + hex_str\n",
    "    return '0x' + hex_str\n",
    "\n",
    "ls = ['-101', '-010' , '0101', '0110', '1010', '+11_111']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + signed_dec2hex(a))\n",
    "    print(a + ' -> ' + signed_dec2hex(a, 3))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0000 -> 0b0\n",
      "0000 -> 0b0000000000\n",
      "------------------------\n",
      "FF -> 0b11\n",
      "FF -> 0b1111111111\n",
      "------------------------\n",
      "f0001 -> 0b10000000000000001\n",
      "位宽参数10 < 16进制补码f0001输出2进制补码0b10000000000000001实际位宽17，请修正位宽参数\n",
      "f0001 -> 0b10000000000000001\n",
      "------------------------\n",
      "0x0000110 -> 0b0100010000\n",
      "0x0000110 -> 0b0100010000\n",
      "------------------------\n",
      "FFFF1 -> 0b10001\n",
      "FFFF1 -> 0b1111110001\n",
      "------------------------\n",
      "11111 -> 0b010001000100010001\n",
      "位宽参数10 < 16进制补码11111输出2进制补码0b010001000100010001实际位宽18，请修正位宽参数\n",
      "11111 -> 0b010001000100010001\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def oneHex2fourBin(one_hex: str) -> str:\n",
    "    '''\n",
    "    函数功能：1位16进制字符串 -> 4位2进制字符串\\n\n",
    "    输入：1位16进制字符串，输入范围0~9, a~f或A~F\\n\n",
    "    输出：4位2进制字符串\n",
    "    '''\n",
    "    if (one_hex == '0'):\n",
    "        return '0000'\n",
    "    elif (one_hex == '1'):\n",
    "        return '0001'\n",
    "    elif (one_hex == '2'):\n",
    "        return '0010'\n",
    "    elif (one_hex == '3'):\n",
    "        return '0011'\n",
    "    elif (one_hex == '4'):\n",
    "        return '0100'\n",
    "    elif (one_hex == '5'):\n",
    "        return '0101'\n",
    "    elif (one_hex == '6'):\n",
    "        return '0110'\n",
    "    elif (one_hex == '7'):\n",
    "        return '0111'\n",
    "    elif (one_hex == '8'):\n",
    "        return '1000'\n",
    "    elif (one_hex == '9'):\n",
    "        return '1001'\n",
    "    elif (one_hex == 'a' or one_hex == 'A'):\n",
    "        return '1010'\n",
    "    elif (one_hex == 'b' or one_hex == 'B'):\n",
    "        return '1011'\n",
    "    elif (one_hex == 'c' or one_hex == 'C'):\n",
    "        return '1100'\n",
    "    elif (one_hex == 'd' or one_hex == 'D'):\n",
    "        return '1101'\n",
    "    elif (one_hex == 'e' or one_hex == 'E'):\n",
    "        return '1110'\n",
    "    elif (one_hex == 'f' or one_hex == 'F'):\n",
    "        return '1111'\n",
    "    else:\n",
    "        int('输入16进制字符' + one_hex + '错误，16进制只能包含0~9, a~f或A~F')\n",
    "\n",
    "def signed_hex2bin(hex_str: str, bin_width: int = -1) -> str:\n",
    "    '''\n",
    "    函数功能：16进制补码字符串 -> 2进制补码字符串\\n\n",
    "    输入参数1：16进制补码字符串，不可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输入参数2：可选，2进制补码字符串宽度，若实际输出宽度>此参数，警告并原样输出；若实际输出宽度<=此参数，高位补若干符号位\\n\n",
    "    输出：2进制补码字符串\n",
    "    '''\n",
    "    input_hex_str = hex_str\n",
    "    hex_str = hex_str.strip()\n",
    "    # 检查输入是否合法，不允许带正负号，首尾不能是下划线，不能出现连续两个下划线\n",
    "    if (hex_str[0] in ['+', '-', '_'] or hex_str[-1] == '_' or '__' in hex_str):\n",
    "        int('输入' + input_hex_str + '不合法，必须为16进制补码，不允许带正负号, '\n",
    "            + '首尾不能是下划线，不能出现连续两个下划线')\n",
    "    elif (hex_str[:2] == '0x'):\n",
    "        hex_str = hex_str[2:]\n",
    "    hex_str = hex_str.replace('_', '') # 输入合法则去除下划线\n",
    "    bin_str = ''\n",
    "    for i in hex_str:\n",
    "        bin_str += oneHex2fourBin(i)\n",
    "    # 去掉2进制补码字符串前面多余的符号位，保留两位\n",
    "    for i in range(len(bin_str)-1):\n",
    "        if (bin_str[i+1] == bin_str[0]):\n",
    "            if (i + 1 == len(bin_str)-1):\n",
    "                bin_str = bin_str[i:]\n",
    "            else:\n",
    "                continue\n",
    "        else:\n",
    "            bin_str = bin_str[i:]\n",
    "            break\n",
    "    if (bin_str == '00'):\n",
    "        bin_str = '0'\n",
    "    if (bin_width == -1):\n",
    "        pass\n",
    "    elif (bin_width < len(bin_str)):\n",
    "        # 实际位宽大于设定位宽则报警告，然后按实际位宽输出\n",
    "        print('位宽参数' + str(bin_width) + ' < 16进制补码' + input_hex_str + '输出2进制补码'\n",
    "            + '0b' + bin_str + '实际位宽' + str(len(bin_str)) + '，请修正位宽参数')\n",
    "    else:\n",
    "        bin_str = bin_str[0] * (bin_width - len(bin_str)) + bin_str # 实际位宽小于设定位宽则补符号位\n",
    "    return '0b' + bin_str\n",
    "\n",
    "ls = ['0000', 'FF' , 'f0001', '0x0000110', 'FFFF1', '11111']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + signed_hex2bin(a))\n",
    "    print(a + ' -> ' + signed_hex2bin(a, 10))\n",
    "    print('------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "00 -> 0\n",
      "------------------------\n",
      "0bFF -> 3071\n",
      "------------------------\n",
      "0x0001 -> 1\n",
      "------------------------\n",
      "0000110 -> 272\n",
      "------------------------\n",
      "FFFF1 -> -15\n",
      "------------------------\n",
      "11111 -> 69905\n",
      "------------------------\n"
     ]
    }
   ],
   "source": [
    "def signed_hex2dec(hex_str: str) -> int:\n",
    "    '''\n",
    "    函数功能：16进制补码字符串 -> 10进制整数\\n\n",
    "    输入：16进制补码字符串，不可带正负号，前后可加任意个 \\\\n 和 空格，数字间可加下划线\\n\n",
    "    输出：10进制整数，只保留负号，正号不保留\n",
    "    '''\n",
    "    return signed_bin2dec(signed_hex2bin(hex_str))\n",
    "\n",
    "ls = ['00', '0bFF' , '0x0001', '0000110', 'FFFF1', '11111']\n",
    "for a in ls:\n",
    "    print(a + ' -> ' + str(signed_hex2dec(a)))\n",
    "    print('------------------------')"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "ac59ebe37160ed0dfa835113d9b8498d9f09ceb179beaac4002f036b9467c963"
  },
  "kernelspec": {
   "display_name": "Python 3.9.6 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.5"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
